/**
 * 常用数据格式验证器
 */
export class Validator {
	/**
	 * 是否是数字
	 * @param value
	 * @returns {boolean}
	 */
	static isNumber(value) {
		if (typeof value === 'number') {
			return true;
		}
		if (typeof value === 'string') {
			return /^[-+]?\d+(\.\d+)?$/.test(value);
		}
		return false;
	}

	/**
	 * 是否是整数
	 * @param value
	 * @returns {boolean}
	 */
	static isInt(value) {
		if (typeof value === 'number') {
			value = value.toString();
		}
		return value && typeof value === 'string' && /^-?\d+$/.test(value);
	}

	/**
	 * 是否是正整数
	 * @param value
	 * @returns {boolean}
	 */
	static isPositiveInt(value) {
		if (typeof value === 'number') {
			value = value.toString();
		}
		return value && typeof value === 'string' && /^\d+$/.test(value);
	}

	static isUUID(value) {
		return !!value && /^[0-9a-f]{32}$/ig.test(value);
	}

	/**
	 * 是否是IPv4格式
	 * @param value
	 * @returns {boolean}
	 */
	static isIpv4(value) {
		return !!value &&
			/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(
				value);
	}

	/***
	 * 是否是IPv4格式或含CIDR后缀
	 * @param value
	 * @returns {boolean}
	 */
	static isIpv4WithCIDR(value) {
		return !!value &&
			/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\/(3[0-2]|[1-2][0-9]|[0-9]))?$/
			.test(value);
	}

	/**
	 * 是否是子网掩码
	 * @param value
	 * @returns {boolean}
	 */
	static isSubnetMask(value) {
		return !!value &&
			/^(((255\.){3}(255|254|252|248|240|224|192|128|0+))|((255\.){2}(255|254|252|248|240|224|192|128|0+)\.0)|((255\.)(255|254|252|248|240|224|192|128|0+)(\.0+){2})|((255|254|252|248|240|224|192|128|0+)(\.0+){3}))$/
			.test(value);
	}

	/**
	 * 是否是Url
	 * @param value {String}
	 * @returns {boolean}
	 */
	static isUrl(value) {
		if (!value) {
			return false;
		}
		// eslint-disable-next-line no-useless-escape
		return /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/ig
			.test(value);
	}

	/**
	 * 是否是相对路径
	 * @param value {String}
	 * @returns {boolean}
	 */
	static isRelativeUrl(value) {
		if (!value) {
			return false;
		}
		return /^([a-z0-9]*:|.{0})\/\/.*$/img.test(value);
	}

	/**
	 * 是否是日期
	 * @param value
	 * @returns {boolean}
	 */
	static isDate(value) {
		return !!value && /^\d{4}-(0?[1-9]|1[0-2])-(0?[1-9]|[12][0-9]|3[01])$/.test(value);
	}

	/**
	 * 是否是日期+时间
	 * @param value
	 * @returns {boolean}
	 */
	static isDatetime(value) {
		return !!value &&
			/^\d{4}-(0?[1-9]|1[0-2])-(0?[1-9]|[12][0-9]|3[01])\s(00|[0-9]|1[0-9]|2[0-3]):([0-9]|[0-5][0-9])(:[0-9]|:[0-5][0-9])?$/
			.test(value);
	}

	static isEmail(value) {
		return !!value && /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/ig.test(value);
	}

	/**
	 * 是否是中文字符
	 * @param value
	 * @returns {boolean}
	 */
	static isChineseCharacter(value) {
		return !!value && /^[\u4e00-\u9fa5]*$/.test(value);
	}

	/**
	 * 是否是域名
	 * @param value
	 * @param allowChinese: 是否允许中文
	 * @returns {boolean}
	 */
	static isDomain(value, allowChinese = false) {
		let reg = allowChinese ?
			/^(?!:\/\/)([a-zA-Z0-9-_]+\.)*[a-zA-Z0-9\u4e00-\u9fa5][a-zA-Z0-9-_\u4e00-\u9fa5]+\.[a-zA-Z]{2,11}?$/igm :
			/^(?!:\/\/)([a-zA-Z0-9-_]+\.)*[a-zA-Z0-9][a-zA-Z0-9-_]+\.[a-zA-Z]{2,11}?$/igm;
		return !!value && reg.test(value);
	}

	/**
	 * 是否是英文或数字
	 * @param value
	 * @returns {boolean}
	 */
	static isEngWithNumber(value) {
		return !!value && /^[a-zA-Z0-9]+$/.test(value);
	}

	/**
	 * 是否是内网IPv4
	 * @param value
	 * @returns {boolean}
	 */
	static isIntranetIpv4(value) {
		return value && /^(127|10|172\.1[6-9]|172\.2[0-9]|172\.3[0-1]|192\.168)\./.test(value) && Validator.isIpv4(
			value);
	}

	/**
	 * 是否前缀几位数是数字
	 * @param value
	 * @param digit 位数
	 * @returns {boolean}
	 */
	static isPrefixNumber(value, digit = 0) {
		if (typeof digit === 'number' && digit > 0) {
			digit--;
		} else {
			digit = 0;
		}
		let re = new RegExp(`^[0-9][0-9]{${digit}}.*$`);
		return !!value && re.test(value);
	}

	/**
	 *是否限制port范围
	 * @param value
	 * @returns {boolean}
	 */
	static isPortRange(value) {
		if (value >= 1 && value <= 65535) {
			return true;
		}
	}

	static isHasSpecialStr(value) {
		let pattern = new RegExp('[`~!@#$%^&*()=|{}.\':;\',\\[\\]<>/?~！@#￥……&*（）——|{}【】‘；：”“\'。，、？]');
		if (pattern.test(value)) {
			return false;
		} else {
			return true;
		}
	}

	static isIpv6(value) {
		return value &&
			/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]+|::(ffff(:0{1,4})?:)?((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9]))$/ig
			.test(
				value);
	}

	static url(url) {
		const regex =
			/^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?"\\+&%$#=~_-]+))*$/;
		return Validator.valid(url, regex, 'URL格式不正确');
	}

	static lowerCase(str) {
		const regex = /^[a-z]+$/;
		return Validator.valid(str, regex, '只能输入小写字母');
	}

	static lowerCaseOrCharacter(str) {
		const regex = /^([a-z]|_|-)+$/;
		return Validator.valid(str, regex, '只能输入小写字母或者-或者_');
	}

	static upperCase(str) {
		const regex = /^[A-Z]+$/;
		return Validator.valid(str, regex, '只能输入大写字母');
	}

	static upperCaseOrCharacter(str) {
		const regex = /^([A-Z]|_|-)+$/;
		return Validator.valid(str, regex, '只能输入大写字母或者-或者_');
	}

	static alphabets(str) {
		const regex = /^[A-Za-z]+$/;
		return Validator.valid(str, regex, '只能输入字母');
	}

	static email(email) {
		const regex =
			/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
		return Validator.valid(email, regex, '邮箱地址格式不正确');
	}

	static mobile(mobile) {
		const regex = /^1\d{10}$/;
		return Validator.valid(mobile, regex, '手机号格式不正确');
	}

	static phone(phone) {
		const regex = /^(0\d{2,3})?-?\d{7,8}$/;
		return Validator.valid(phone, regex, '电话号码格式不正确');
	}

	static postcode(postcode) {
		const regex = /^[0-9][0-9]{5}$/;
		return Validator.valid(postcode, regex, '邮编格式不正确');
	}

	static number(num) {
		const regex = /^\d+$/;
		return Validator.valid(num, regex, '只能输入纯数字');
	}

	static fax(fax) {
		const regex = /^(\d{3,4}-)?\d{7,8}$/;
		return Validator.valid(fax, regex, '传真格式不正确');
	}

	static int(num) {
		const regex = /^((0)|([1-9]\d*))$/;
		return Validator.valid(num, regex, '只能输入非负整数');
	}

	static intPlus(num) {
		const regex = /^[1-9]\d*$/;
		return Validator.valid(num, regex, '只能输入正整数');
	}

	static float1(num) {
		const regex = /^-?\d+(\.\d)?$/;
		return Validator.valid(num, regex, '只能输入数字，最多一位小数');
	}

	static float2(num) {
		const regex = /^-?\d+(\.\d{1,2})?$/;
		return Validator.valid(num, regex, '只能输入数字，最多两位小数');
	}

	static float3(num) {
		const regex = /^-?\d+(\.\d{1,3})?$/;
		return Validator.valid(num, regex, '只能输入数字，最多三位小数');
	}

	static floatPlus3(num) {
		const regex = /^\d+(\.\d{1,3})?$/;
		return Validator.valid(num, regex, '只能输入数字，最多三位小数');
	}

	static encode(code) {
		const regex = /^(_|-|[a-zA-Z0-9])+$/;
		return Validator.valid(code, regex, '编码只能使用字母、数字、下划线、中划线');
	}

	static encode2(code) {
		const regex = /^[a-zA-Z0-9]+$/;
		return Validator.valid(code, regex, '编码只能使用字母、数字');
	}

	static encode3(code) {
		const regex = /^(_|[a-zA-Z0-9])+$/;
		return Validator.valid(code, regex, '编码只能使用字母、数字、下划线');
	}

	static idCard(code) {
		const regex =
		/^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
		return Validator.valid(code, regex, '请输入正确的身份证号码');
	}

	static uscc(code) {
		const regex = /^[0-9A-Z]{18}/;
		return Validator.valid(code, regex, '请输入正确的社会信用号');
	}

	static carNum(code) {
		const regex =
			/^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$/i;
		return Validator.valid(code, regex, '请输入正确的车牌号');
	}

	static cnandEN(code) {
		const regex = /^[a-zA-Z\u4e00-\u9fa5]+$/;
		return Validator.valid(code, regex, '只能使用中文、英文');
	}

	static mobileOrPhone(val) {
		const result = /^1\d{10}$/.test(val) || /^(0\d{2,3})?-?\d{7,8}$/.test(val);
		return Validator.valid(result, null, '手机或电话号格式不正确');
	}

	static length(val) {
		return Validator.valid(val, null, '字符长度不正确');
	}

	static valid(val, regex, msg) {
		return {
			result: regex instanceof RegExp ? regex.test(val) : !!val,
			errMsg: msg
		};
	}
}

window.Validator = Validator;
